package com.huqu.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.huqu.dao.S100Dao;
import com.huqu.entities.S100;

public class LuceneControl {

	private static Version version = Version.LUCENE_4_10_2;

	// kiểm tra xem url này đã tồn tại trong CSDL chưa ?
	public static List<S100> checkExitsUrl(String url) {
		List<S100> list = new ArrayList<S100>();
		try {
			S100Dao s100Dao = (S100Dao) ApplicationHelper
					.findBean(ApplicationConstant.REPOSITORY_NAME_S100);
			list = s100Dao.ListOfTabS100Check(url);
			return list;
		} catch (Exception e) {
			e.printStackTrace();
			return list;
		}
	}

	// kiểm tra xem url có hợp lệ hay không ?
	public static boolean checkUrl(String url) {
		if (url != null && url.length() > 0 && url.indexOf("mailto:") < 0) {
			return true;
		} else {
			return false;
		}
	}

	// insert nội dung của url vào csdl
	public static int insertS100(S100 s100) {
		try {
			S100Dao s100Dao = (S100Dao) ApplicationHelper
					.findBean(ApplicationConstant.REPOSITORY_NAME_S100);
			int result = s100Dao.InsertTabS100(s100.getPs100(),
					s100.getSv101(), s100.getSv102(), s100.getSv103(),
					s100.getSn107(), s100.getSn108());
			if (result > 0) {
				return result;
			} else
				return 0;
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
	}

	// tự động quét các link trong url, nếu cái nào chưa có trong CSDL thì
	// insert xuống, nếu có rồi kiểm tra xem ngày cập nhật nếu lớn hơn 3 ngày
	// trước thì update lại nội dung
	public static void getDetailUrl2(String url) {
		try {
			org.jsoup.nodes.Document doc = Jsoup.connect(url).get();
			System.out.println("Fetching " + url + "...");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static boolean getDetailUrlToInsert(String url) {
		try {
			System.out.println("Fetching " + url + "...");
			org.jsoup.nodes.Document doc = Jsoup.connect(url).get();
			S100 s100 = new S100();
			s100.setPs100(-1);

			if (doc != null) {
				// kiểm tra xem url đã tồn tại hay chưa ?
				List<S100> listS100 = checkExitsUrl(url);
				if (listS100.size() > 0) {
					S100 s100temp = listS100.get(0);

					// đã tồn tại thì kiem tra xem ngay cap nhat co phai 3 ngày
					// truoc ko roi update lại
					if (ApplicationHelper.isDayAgo(s100temp.getSd105(), 3)) {
						// System.out.println("du dieu kien update");
						s100.setPs100(s100temp.getPs100());
						s100.setSv101(s100temp.getSv101());
						s100.setSv102(doc.title());
						s100.setSv103(doc.text());
						s100.setSn107(0); // cập nhật lại trạng thái đánh chỉ
											// mục
						s100.setSn108(s100temp.getSn108());
					} else {
						// System.out.println("khong du dieu kien update");
					}

				} else {
					// chưa tồn tại thì insert mới
					// System.out.println("du dieu kien insert moi");
					s100.setPs100(0);
					s100.setSv101(url);
					s100.setSv102(doc.title());
					s100.setSv103(doc.text());
					s100.setSn107(0);
					s100.setSn108(3);
				}

				if (s100.getPs100() != -1) {
					S100Dao s100Dao = (S100Dao) ApplicationHelper
							.findBean(ApplicationConstant.REPOSITORY_NAME_S100);
					int result = s100Dao.InsertTabS100(s100.getPs100(),
							s100.getSv101(), s100.getSv102(), s100.getSv103(),
							s100.getSn107(), s100.getSn108());
					System.out.println("----result= " + result);
					if (result > 0) {
						return true;
					} else
						return false;
				} else
					return false;
			} else {
				return false;
			}

		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	// tu dong quet cac link co trong url
	public static void autoInsertFromUrl(String url) {
		try {
			org.jsoup.nodes.Document doc = Jsoup.connect(url).get();
			System.out.println("bắt đầu quét : " + url + "...");
			if (doc != null) {
				Elements links = doc.select("a[href]");
				for (Element link : links) {
					String urlLink = link.attr("abs:href");
					LuceneControl.getDetailUrlToInsert(urlLink);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// load danh sach cac link tim kiem
	public static List<S100> loadListS100() {
		try {
			S100Dao s100Dao = (S100Dao) ApplicationHelper
					.findBean(ApplicationConstant.REPOSITORY_NAME_S100);
			List<S100> list = s100Dao.ListOfTabS100(0, 0, 3);
			System.err.println("ListS100.size()= " + list.size());
			return list;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	// đánh chỉ mục
	public static void createIndex(List<S100> listS100) {
		try {
			// Create a File object with theFile name of the Lucene index and
			// open that index: "src//main//webapp//lucene"
			File file = new File(ApplicationConstant.PATHFILE);
			FSDirectory directory = FSDirectory.open(file);

			// Create an analyzer that will be used with the IndexWriter:
			Analyzer analyzer = new StandardAnalyzer(version);
			Analyzer sss= new StandardAnalyzer();

			// Build an IndexWriterConfig to use as the configuration for the
			// indexWriter:
			IndexWriterConfig indexWriterConfig = new IndexWriterConfig(
					version, analyzer);
			indexWriterConfig
					.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

			// Build the indexWriter:
			IndexWriter writer = new IndexWriter(directory, indexWriterConfig);

			for (S100 s100 : listS100) {
				Document doc = new Document();
				doc.add(new IntField(ApplicationConstant.FIELD_PS100, s100
						.getPs100(), Field.Store.YES));
				doc.add(new TextField(ApplicationConstant.FIELD_SV101, s100
						.getSv101(), Field.Store.YES));
				doc.add(new TextField(ApplicationConstant.FIELD_SV102, s100
						.getSv102(), Field.Store.YES));
				doc.add(new TextField(ApplicationConstant.FIELD_SV103, s100
						.getSv103(), Field.Store.YES));
				writer.addDocument(doc);
			}

			writer.commit();
			writer.close();
			analyzer.close();
			directory.close();
			System.err.println("Đánh chỉ mục hoàn thành");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// convert document thành đối tượng S100
	public static S100 convertDocumentToS100(Document doc) {
		try {
			S100 s100 = new S100();
			s100.setPs100(Integer.parseInt(doc
					.get(ApplicationConstant.FIELD_PS100)));
			s100.setSv101(doc.get(ApplicationConstant.FIELD_SV101));
			s100.setSv102(doc.get(ApplicationConstant.FIELD_SV102));
			s100.setSv103(doc.get(ApplicationConstant.FIELD_SV103));
			return s100;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	// tìm kiếm chỉ mục keysearch với 3 trường url, tiêu đề, nội dung
	public static ScoreDoc[] searchIndex(String keySearch, int numHits) {
		try {
			System.out.println("---searchIndex");
			List<ScoreDoc> listScoreDoc = new ArrayList<ScoreDoc>();
			Directory directory = FSDirectory.open(new File(
					ApplicationConstant.PATHFILE));
			IndexReader indexReader = DirectoryReader.open(directory);
			IndexSearcher indexSearcher = new IndexSearcher(indexReader);
			StandardAnalyzer analyzer = new StandardAnalyzer(version);
			// null: hoặc ta có thể chọn các File khác
			QueryParser querypaser = new QueryParser(version, null,
					new StandardAnalyzer(version));
			System.err.println(createQuerySearch(keySearch));
			Query query = querypaser.parse(createQuerySearch(keySearch));

			TopScoreDocCollector collector = TopScoreDocCollector.create(
					numHits, true);
			
			indexSearcher.search(query, collector);
			ScoreDoc[] hitsDocs = collector.topDocs().scoreDocs;
			for (ScoreDoc srore : hitsDocs) {
				listScoreDoc.add(srore);
			}
			/*for (int i = 0; i < hitsDocs.length; i++) {
				int docid = hitsDocs[i].doc;
				Document d = indexSearcher.doc(docid);
				if (d != null) {
					System.out.println(d.get("id") + "-----" + d.get("ps100")
							+ "----" + d.get("sv101") + "----" + d.get("sv102"));
				} else {
					System.out.println("Khong co ket qua.");
				}
			}*/

			return hitsDocs;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	// lấy kết quả từ việc tìm kiếm rồi convert sang S100
	public static List<S100> getResultSearch(ScoreDoc[] hitsDocs,
			int offset, int limit) {
		try {
			System.out.println("---getResultSearch");
			List<S100> listS100 = new ArrayList<S100>();
			Directory directory = FSDirectory.open(new File(
					ApplicationConstant.PATHFILE));
			IndexReader indexReader = DirectoryReader.open(directory);
			IndexSearcher indexSearcher = new IndexSearcher(indexReader);
			
			int max = offset + limit;
			if (max > hitsDocs.length) {
				max = hitsDocs.length;
			}
			if((offset-1)<0){
				offset=1;
			}
			for (int i = offset-1; i < max; i++) {
				int docid = hitsDocs[i].doc;
				Document d = indexSearcher.doc(docid);
				if (d != null) {
					/*System.out.println(d.get("id") + "-----" + d.get("ps100")
							+ "----" + d.get("sv101") + "----" + d.get("sv102"));*/
					listS100.add(convertDocumentToS100(d));
				} else {
					System.out.println("Khong co ket qua.");
				}
			}

			return listS100;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	// tạo cấu query để tìm kiếm
	public static String createQuerySearch(String keySearch) {
		
		return ApplicationConstant.FIELD_SV101 + ": \"" + keySearch + "\" OR "
				+ ApplicationConstant.FIELD_SV102 + ":\"" + keySearch + "\" OR "
				+ ApplicationConstant.FIELD_SV103 + ": \"" + keySearch+"\"";
		//return ApplicationConstant.FIELD_SV101 + ":" + keySearch;
	}

}
